using System.Windows.Media;
using System.Windows.Media.Media3D;

namespace Sensor.UI.PointClouds;

/// <summary>
/// 箭头工厂类，用于创建3D箭头模型
/// </summary>
public static class ArrowFactory
{
    /// <summary>
    /// 创建由圆柱和圆锥组合的红色箭头
    /// </summary>
    /// <param name="origin">箭头起点</param>
    /// <param name="direction">箭头方向向量</param>
    /// <param name="length">箭头长度</param>
    /// <param name="radius">箭头半径</param>
    /// <param name="headLengthRatio">箭头头部占总长度的比例</param>
    /// <param name="headRadiusRatio">箭头头部半径与箭头半径的比例</param>
    /// <returns>箭头模型</returns>
    public static Model3D CreateArrow(Point3D origin, Vector3D direction, double length = 1.0, double radius = 0.1, 
        double headLengthRatio = 0.3, double headRadiusRatio = 2.0)
    {
        var group = new Model3DGroup();
        
        // 归一化方向向量
        direction.Normalize();
        
        // 计算圆柱和圆锥的参数
        var cylinderLength = length * (1 - headLengthRatio);
        var coneLength = length * headLengthRatio;
        var coneRadius = radius * headRadiusRatio;
        
        // 创建圆柱体（箭头杆部）
        var cylinder = CreateCylinder(origin, direction, cylinderLength, radius, Colors.Red);
        group.Children.Add(cylinder);
        
        // 计算圆锥起点位置
        var coneOrigin = origin + direction * cylinderLength;
        
        // 创建圆锥体（箭头头部）
        var cone = CreateCone(coneOrigin, direction, coneLength, coneRadius, Colors.Red);
        group.Children.Add(cone);
        
        return group;
    }
    
    /// <summary>
    /// 创建圆柱体
    /// </summary>
    private static Model3D CreateCylinder(Point3D origin, Vector3D direction, double height, double radius, Color color)
    {
        var mesh = new MeshGeometry3D();
        
        // 计算垂直于方向的向量
        Vector3D up = new Vector3D(0, 1, 0);
        if (Math.Abs(direction.Y) > 0.9)
        {
            up = new Vector3D(1, 0, 0);
        }
        
        Vector3D right = Vector3D.CrossProduct(direction, up);
        right.Normalize();
        up = Vector3D.CrossProduct(right, direction);
        up.Normalize();
        
        // 创建圆柱体的顶点
        int segments = 16;
        double angleStep = 2 * Math.PI / segments;
        
        // 底部圆心
        mesh.Positions.Add(origin);
        
        // 底部圆周上的点
        for (int i = 0; i < segments; i++)
        {
            double angle = i * angleStep;
            Vector3D offset = radius * (Math.Cos(angle) * right + Math.Sin(angle) * up);
            mesh.Positions.Add(origin + offset);
        }
        
        // 顶部圆心
        Point3D topCenter = origin + direction * height;
        mesh.Positions.Add(topCenter);
        
        // 顶部圆周上的点
        for (int i = 0; i < segments; i++)
        {
            double angle = i * angleStep;
            Vector3D offset = radius * (Math.Cos(angle) * right + Math.Sin(angle) * up);
            mesh.Positions.Add(topCenter + offset);
        }
        
        // 创建三角形
        // 底部
        for (int i = 0; i < segments; i++)
        {
            int next = (i + 1) % segments;
            mesh.TriangleIndices.Add(0);
            mesh.TriangleIndices.Add(i + 1);
            mesh.TriangleIndices.Add(next + 1);
        }
        
        // 顶部
        int topCenterIndex = 1 + segments;
        for (int i = 0; i < segments; i++)
        {
            int next = (i + 1) % segments;
            mesh.TriangleIndices.Add(topCenterIndex);
            mesh.TriangleIndices.Add(topCenterIndex + next + 1);
            mesh.TriangleIndices.Add(topCenterIndex + i + 1);
        }
        
        // 侧面
        for (int i = 0; i < segments; i++)
        {
            int next = (i + 1) % segments;
            int bottomCurrent = i + 1;
            int bottomNext = next + 1;
            int topCurrent = topCenterIndex + i + 1;
            int topNext = topCenterIndex + next + 1;
            
            // 两个三角形组成一个矩形侧面
            mesh.TriangleIndices.Add(bottomCurrent);
            mesh.TriangleIndices.Add(bottomNext);
            mesh.TriangleIndices.Add(topCurrent);
            
            mesh.TriangleIndices.Add(bottomNext);
            mesh.TriangleIndices.Add(topNext);
            mesh.TriangleIndices.Add(topCurrent);
        }
        
        // 创建材质
        var material = new DiffuseMaterial(new SolidColorBrush(color));
        return new GeometryModel3D(mesh, material);
    }
    
    /// <summary>
    /// 创建圆锥体
    /// </summary>
    private static Model3D CreateCone(Point3D origin, Vector3D direction, double height, double radius, Color color)
    {
        var mesh = new MeshGeometry3D();
        
        // 计算垂直于方向的向量
        Vector3D up = new Vector3D(0, 1, 0);
        if (Math.Abs(direction.Y) > 0.9)
        {
            up = new Vector3D(1, 0, 0);
        }
        
        Vector3D right = Vector3D.CrossProduct(direction, up);
        right.Normalize();
        up = Vector3D.CrossProduct(right, direction);
        up.Normalize();
        
        // 创建圆锥体的顶点
        int segments = 16;
        double angleStep = 2 * Math.PI / segments;
        
        // 底部圆心
        mesh.Positions.Add(origin);
        
        // 底部圆周上的点
        for (int i = 0; i < segments; i++)
        {
            double angle = i * angleStep;
            Vector3D offset = radius * (Math.Cos(angle) * right + Math.Sin(angle) * up);
            mesh.Positions.Add(origin + offset);
        }
        
        // 顶部顶点
        Point3D topPoint = origin + direction * height;
        mesh.Positions.Add(topPoint);
        
        // 创建三角形
        // 底部
        for (int i = 0; i < segments; i++)
        {
            int next = (i + 1) % segments;
            mesh.TriangleIndices.Add(0);
            mesh.TriangleIndices.Add(next + 1);
            mesh.TriangleIndices.Add(i + 1);
        }
        
        // 侧面
        int topIndex = 1 + segments;
        for (int i = 0; i < segments; i++)
        {
            int next = (i + 1) % segments;
            int bottomCurrent = i + 1;
            int bottomNext = next + 1;
            
            mesh.TriangleIndices.Add(bottomCurrent);
            mesh.TriangleIndices.Add(bottomNext);
            mesh.TriangleIndices.Add(topIndex);
        }
        
        // 创建材质
        var material = new DiffuseMaterial(new SolidColorBrush(color));
        return new GeometryModel3D(mesh, material);
    }
}